home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
dirut
/
rm_om.zip
/
FORMATCH.C
< prev
next >
Wrap
Text File
|
1988-12-24
|
6KB
|
179 lines
/*
** Match the directory pattern given, and call user-supplied routine
** once for each match of a pattern with a pointer to the current
** FILE_MATCH packet as argument. The routine can interrupt the match
** process by returning a nonzero value.
** Argument type governs the attributes of the file searched for,
** the low bits (masked by ALLREALONES) being the normal DOS file
** attributes, while the rest are used to control the match algorithm.
** Specifically:
** READONLY,HIDDEN,SYSTEM,VOLABEL,DIRECTORY,ARCHIVE
** these are the normal DOS file attributes. If VOLABEL is specified,
** only the specified disk volume label will be found. If any of the
** bits READONLY, HIDDEN, SYSTEM, and DIRECTORY are specified, the
** match will find normal files and any files with these attributes
** set. The ARCHIVE bit cannot be used for searching.
** DOTHIDDEN
** if set, filenames starting with a dot '.' are considered hidden,
** and the HIDDEN bit must be on to retrieve any of these filenames,
** except if the name is given as a pattern
** MATCHNONWILD
** return non-wildcard match items as themselves, even if they do
** not exist
** RECURSIVE
** must have DIRECTORY set also; match recursively, returning the
** directory as the last member of itself; initial pattern must be
** nonwildcard
** DIRFIRST
** used with RECURSIVE; return the directory as the first member of
** itself as opposed to the default of last member
** When any of "x:", "x:/" and "/" are given as patterns, a "*.*" is
** appended to them automagically (this makes RECURSIVE matching behave
** more logically with all directories).
**
** Returns codes as value:
** >0 OK, number of times user routine was called
** 0 no match
** -1 user routine returned nonzero
**
** (c) 1988 by Otto Makela, Jyvaskyla, Finland
*/
#include <model.h>
#include <ctype.h>
#include "formatch.h"
#define SETDMA 0x1a
#define SRCHFIR 0x4e
#define SRCHNXT 0x4f
#ifdef _LARGEDATA
#define BDOS bdosx
#define DOS dosx
#else
#define BDOS bdos
#define DOS dos
#endif
char *getenv();
char optsepar[2]="/",dirsepar='\\',othersepar='/';
int formatch(path,type,routine)
char *path;
int type;
int (*routine)(); {
int i,code,count=0,wilds=0;
register char *p,c;
char *q,*restname;
char *wildcard="*.*";
FILE_MATCH file_match;
#ifdef DEBUG
printf("formatch(\"%s\",0x%x)\n",path,type);
#endif
BDOS(SETDMA, &file_match);
/* Copy initial pattern up to last '/' to match.filename;
set restname to last wildcard tail */
for(p=file_match.filename, restname=p, q=path; c=*q; *q++=c) {
if(c==':' || c==dirsepar || c==othersepar) {
if(c!=':') c=dirsepar;
restname=p+1;
} else if(c=='*' || c=='?')
wilds++;
if(isupper(c))
*p++=c=tolower(c);
else
*p++=c;
}
/* Non-wildcard matches: add "*.*" */
if(!wilds) {
p=path;
if(isalpha(p[0]) && p[1]==':') p+=2;
if(p[0]=='.') {
if(!p[1] || (p[1]=='.' && !p[2])) {
if(p[1]) {
p+=2;
*p++=dirsepar;
}
*p='\0';
}
} else if(p[0]==dirsepar && !p[1])
p++;
if(!*p) {
strcpy(file_match.filename,path);
restname=file_match.filename+(p-path);
strcpy(p,wildcard);
wilds=2;
}
}
/* Then repeat until we run out of matches or user routine breaks */
again:
for(code=SRCHFIR; DOS(code,0,ALLREALONES&type,path)!=-1; code=SRCHNXT) {
/* Proceed to next one, if starts with dot and DOTHIDDEN */
if((type&(DOTHIDDEN|HIDDEN))==DOTHIDDEN &&
*file_match.shortname=='.' && *restname!='.') continue;
/* Copy shortname to full filename */
for(p=file_match.shortname, q=restname; *q++=*p=tolower(*p); p++);
/* Recurse if a directory name, but not "." or ".." */
if(type&RECURSIVE && file_match.attribute&DIRECTORY &&
(*file_match.shortname!='.' || !wilds)) {
#ifdef DEBUG
printf( "type&RECURSIVE=%02x, file_match.attribute&"
"DIRECTORY=%02x, *file_match.shortname=%c, "
"!wilds=%d\n",type&RECURSIVE,file_match.attribute&
DIRECTORY,*file_match.shortname,!wilds);
#endif
/* Call user routine before anything else if DIRFIRST */
if(type&DIRFIRST)
if(routine(&file_match)) return(-1);
else count++;
/* Then add wildcard to filename and call us again */
q[-1]=dirsepar;
strcpy(q,wildcard);
if((i=formatch(file_match.filename,type,routine))==-1) return(-1);
/* Have to redo this because our other incarnation messed it */
BDOS(SETDMA, &file_match);
count+=i;
q[-1]='\0';
if(type&DIRFIRST) continue;
}
/* Call user routine only if not recursing and not at a '.';
** then return minus one if user routine breaks, else zero
*/
if(!(type&RECURSIVE) || !(file_match.attribute&DIRECTORY) ||
(*file_match.shortname!='.') || !wilds)
if(routine(&file_match)) return(-1);
else count++;
}
/* If no wildcards, just test the filename */
if(!wilds && !count && type&MATCHNONWILD) {
for(p=file_match.shortname, q=restname; *p++=*q++;);
file_match.attribute=0;
file_match.filetime=0L;
file_match.filesize=0L;
if(routine(&file_match)) return(-1);
else count++;
}
/* Return number of times user routine called */
return(count);
}
/*
** The first time 'round, get option and file separators
*/
void initmatch() {
register char *p;
if( (*optsepar = (p=getenv("SWITCHAR"))?*p:switchar(0)) == '/')
dirsepar='\\', othersepar='/';
else
dirsepar='/', othersepar='\\';
}